package shining365.programmableweb.data.app;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.JAXBException;

import org.apache.log4j.Logger;

public class ApiCentrality extends AppBasic {

	public ApiCentrality(Date endDate) throws IOException, JAXBException {
		super(endDate, false, OrderBy.USE_COUNT);
		logger.debug("ApiCentrality: until " + endDate);
	}
	
	public Map<String, Double> getApiCentralities() {
		Map<String, Double> api2centrality = new HashMap<String, Double>();
		
		for (int i = 0; i < nNodes; i++) {
			graph[i][i] = Double.MAX_VALUE;
		}
		double[][] d = 
			reciprocal(allPairsShortestPaths(reciprocal(graph.clone())));
		for (int i = 0; i < nNodes; i++) {
			d[i][i] = 0;
		}
		
		double sum = 0;
		for (double[] e : d) {
			for (double f : e) {
				sum += f;
			}
		}
		api2centrality.put("AVERAGE", sum / ((nNodes - 1) * nNodes));
		
		//统计每个api与其他api的平均亲和度（即中心度）
		for (int i = 0; i < nNodes; i++) {
			//本api与其他api的亲和度总和
			double s = 0;
			for (double e : d[i]) {
				s += e;
			}
			api2centrality.put(apis.get(i).getUrl(), s / (nNodes - 1));
		}
		
		return api2centrality;
	}
	
	private static double[][] allPairsShortestPaths(double[][] w) {
		final int n = w.length;
		double[][] l = w.clone();
		for (int i = 2; i <= n - 1; i++) {
			l = extendShortestPaths(l, w);
		}
		return l;
	}
	
	private static double[][] extendShortestPaths(double[][] l, double[][] w) {
		final int n = l.length;
		double[][] lp = new double[n][n];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				lp[i][j] = Double.MAX_VALUE;
				for (int k = 0; k < n; k++) {
					lp[i][j] = Math.min(lp[i][j], l[i][k] + w[k][j]);
				}
			}
		}
		return lp;
	}
	
	private static double[][] reciprocal(double[][] d) {
		final int n = d.length;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (d[i][j] == 0) {
					d[i][j] = Double.MAX_VALUE;
				} else if (d[i][j] == Double.MAX_VALUE) {
					d[i][j] = 0;
				} else {
					d[i][j] = 1 / d[i][j];
				}
			}
		}
		return d;
	}
	
	private static final Logger logger = Logger.getLogger(ApiCentrality.class);
}
